<?php
/*
 * MinPlan "API"
 * Code: wizt, anemos, ThanE
 * REMEMBER: /tbody/ SHOULD NOT be used in xPath, just skip it
 */

session_start();

// Error report everything
error_reporting(E_ALL & E_STRICT);

// Initialize classes
require_once('classes/fetcher.php');
require_once('classes/page_handler.php');
require_once('classes/user.php');
require_once('classes/courses.php');

$fetcher = new Fetcher;
$page_handler = new Page_Handler;
$user = new User;
$courses = new Courses;

// Gets the current page (without subfolders)
$currentPage = basename($_SERVER['PHP_SELF']);

// Takes a get() page and creates an XML and then xPath the XML
function xPathify(&$content, $path) {

    $dom = new DOMDocument();
    @$dom->loadHTML($content);
    $xpath = new DOMXPath($dom);
    $result = $xpath->query($path);

    return $result;
}

// Create an object that stores all the information about the person
class person {
    public $name;
    public $inst;
    public $courses = array();
	public $authed = false;

    public function getInfo() {
    	$fak = explode('-', $this->inst);
        echo "$this->name ($fak[0])";
		//print_r($this->inst);
    }
}

class course {
    public $goal;
    public $page;
    public $when;
    public $info = array();
    public $sp;
    public $name;

    function printCourse() {
        echo "<br /><br />Kursnamn: ".$this->name;
        echo "<br />Målsättning: ".$this->goal;
        echo "<br />Kurssida: <a href=\"$this->page\">".$this->page."</a>";
        echo "<br />Tidpunk: ".$this->when;
        echo "<br />Studiepoäng: ".$this->sp;
    }
}

// Magic mushroom
class scraper {
    private $options = array();
    private $connected = false;
    private $lastPage = 'informationMessages.do';
    private $mainPage = 'https://minplan.abo.fi/minplan/';
    private $changePage = 'actionDispatch=%2Fga_moduletab.do';
    private $courseInfo = 'actionDispatch=my_registrations_my_course_registrations_ejb_goto';
    private $searchExam = 'actionDispatch=course_lov_view_search';
    private $examPage = 'actionDispatch=my_registrations_view_tab';
    public $loginPage;

    function __construct ($uCookie = null) {
		if (!stristr(PHP_OS, 'WIN')) { 
		 $uCookie .= '/tmp/';
		}
        $cookies = ''.$uCookie.'cookies.txt';
        $this->options = array(
            CURLOPT_SSL_VERIFYPEER => false, // Needed for https://
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6',
            CURLOPT_HEADER => false, // Add response headers to return, for testing
            CURLOPT_FOLLOWLOCATION => true, // Follow if the site redirects
            CURLOPT_AUTOREFERER => true,
            CURLOPT_RETURNTRANSFER => true, // Add html to return
            CURLOPT_FAILONERROR => true,
            CURLOPT_COOKIEJAR  => $cookies, // Create cookies
            CURLOPT_COOKIEFILE => $cookies,
        );
    }
    function get ($url) {

        $ch = curl_init();

        $options = $this->options;
        $options[CURLOPT_URL] = $url;
        //print_r($options);
        curl_setopt_array($ch, $options);
        $results = curl_exec($ch);

        if (!$results) {
            echo "<br /><b>Ett fel uppstod när sidan skulle hämtas</b>";
            echo "<br />cURL error number:" .curl_errno($ch);
            echo "<br />cURL error:" . curl_error($ch);
            exit;
        }

        //Close curl session
        curl_close($ch);

        //print utf8_encode($results);
        return $results;
    }

    // Logs in, and returns the login information (name and inst)
    function login ($username, $password) {
        $loginPerson = new person;

        $loginPage = $this->get("https://minplan.abo.fi/minplan/login.do?actionDispatch=login_view_dologin&selectedUserLoginName=".$username."&selectedUserLoginPassword=".$password."");

        $xName = xPathify($loginPage, '/html/body/form/table/tr[2]/td/table/tr[2]/td[2]/table/tr[3]/td/div[2]');
        $xInst = xPathify($loginPage, '/html/body/form/table/tr[2]/td/table/tr[2]/td[2]/table/tr[3]/td/div[4]');
		if(isset($xName->item(0)->nodeValue)) {
	        $loginPerson->name = $xName->item(0)->nodeValue;
	        $loginPerson->inst = $xInst->item(0)->nodeValue;
			$loginPerson->authed = ($loginPerson->name != null);
		} else {
			echo('<h1>Fel login/pass</h1>');
		}

        return $loginPerson;

    }

    function logout () {
        $loginPage = $this->get('https://minplan.abo.fi/minplan/informationMessages.do?actionDispatch=%2Fga_logout.do');
		session_destroy();
    }

	function addExam($row) {

        $this->get($this->mainPage."courseLOV.do?actionDispatch=course_lov_view_select&selectedCourseSearchStateScope=active&courseLOVListHandler.page[".$row."].selected=on");

    }

    function searchExam($code,$years=null,$period=null) {
        /* TODO!
        * You can't search on the semester/period directly yet.
        * $code should be in format xxxxx.x NOT xxxxx.x.x
        */
        $this->getExams();
        $this->get("https://minplan.abo.fi/minplan/myRegistrationsMyExaminationRegistrations.do?actionDispatch=my_registrations_my_examination_registrations_add_course_to_lov");
        $results = $this->get($this->mainPage."courseLOV.do?".$this->searchExam."&courseCode=".$code);
        $this->lastPage = 'courseLOV.do';

        return $results;
    }

    function searchCourse($name, $years=null, $period=null, $page=null) {

        $name = str_replace(" ","+",$name);
        $this->getCourses();
        $this->get("https://minplan.abo.fi/minplan/myRegistrationsMyCourseRegistrations.do?actionDispatch=my_registrations_my_course_registrations_add_course_to_lov");
        $results = $this->get("https://minplan.abo.fi/minplan/courseLOV.do?actionDispatch=course_lov_view_search&identifier=".$page."&courseSearchCriteria.yearCode=".$years."&courseSearchCriteria.freetext=".$name."");
        $results = $this->get($this->mainPage."courseLOV.do?actionDispatch=%2Fga_list_handler_paging_loadondemand.do&identifier=".$page."&listHandlerName=fi.abo.minplan.web.formbean.CourseLOVForm&listHandlerProperty=courseLOVListHandler");
        return $results;
    }

    function getInformation() {
        $results = $this->get($this->mainPage."".$this->lastPage."?".$this->changePage."&identifier=information");
        $this->lastPage = 'informationMessages.do';
        return $results;
    }

    function getStudyplan() {
        $results = $this->get($this->mainPage."".$this->lastPage."?".$this->changePage."&identifier=my_study_plans");
        $this->lastPage = 'myStudyPlanMyStudyPlans.do';
        return $results;
    }

    function getCourses() {

        $this->get($this->mainPage."courseLOV.do?actionDispatch=%2Fga_moduletab.do&identifier=my_registrations");
        $results = $this->get($this->mainPage."myRegistrationsMyExaminationRegistrations.do?actionDispatch=my_registrations_view_tab&identifier=my_registrations_my_course_registrations_tab");
        $this->lastPage = 'myRegistrationsMyCourseRegistrations.do';
        return $results;
    }

    function getCourse($CID) {
        // Get the "mycourses" page first, else it won't work
        $this -> getCourses();
        // Get the course, course id and a year ID is required
        $results = $this->get($this->mainPage."myRegistrationsMyCourseRegistrations.do?".$this->courseInfo."&identifier=".$CID);
        $this->lastPage = "ejb_view.do";
        return $results;
    }

    function createCList($html) {
        //print $html;
        $results = array(array());
        $list = xPathify($html,'/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[2]/tr/td/table/tr/td/table/tr/td/table/tr');
        /* Structure:
         * 0: Titles
         * 1: "Kurser i mina studieplaner"
         * 2: Years
         * 3->X: Course - Empty - Course ... Course - Empty
         * X: "Valda kurser utanför mina studieplaner"
         * X+1: Years
         * X+2 -> End: Course - Empty - Course ... Course - Empty
         */

        $cCode = xPathify($html, '/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[2]/tr/td/table/tr/td/table/tr/td/table/tr[4]/td/span');
        $code = preg_split("/[a-zA-Z',:_()]+/",$cCode->item(0)->getAttributeNode('onclick')->nodeValue);

        $j = 0;
        $extraCourse = 0;
        for ($i = 3; $i<$list->length; $i++) {

            if (strpos($list->item($i)->nodeValue, "Valda kurser utanför mina studieplaner")) {
                $i = $i+2;
                $extraCourse = 1;
            }

            if ($i%2 == 1) {
                $cCode = xPathify($html, "/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[2]/tr/td/table/tr/td/table/tr/td/table/tr[".($i+1)."]/td/span");
                $code = preg_split("/[a-zA-Z',:_()]+/",$cCode->item(0)->getAttributeNode('onclick')->nodeValue);
                $result = $list->item($i)->nodeValue;

                $text = preg_split("/[0-9,.]+/", $result);

                $results[$j]['code'] = $code[1];
                $results[$j]['name'] = $text[1];

                if ($extraCourse) $results[$j]['extra'] = 1;

                $j++;
            }
        }

		global $currentPage;
        for ($i=0; $i < sizeof($results); $i++) {
            print "<br/>";
            print $results[$i]['code']."|";
            print "<a href=\"".$currentPage."?action=getCourse&amp;course=".$results[$i]['code']."\">".$results[$i]['name']."</a>";
            print " | <a href=\"".$currentPage."?action=searchExam&amp;course=".$results[$i]['code']."\">(Sök tent)</a>";

            if (isset($results[$i]['extra'])) print " | (Utanför studieplan)";
            print "<br/>";
        }

        // Multidimensional array ("4 dimensions")
        return $results;
    }

    function scrapeCourse($html) {

        $temp = new Course();

        $page = xPathify($html,'/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[1]/tr[2]/td[2]/table/tr/td');
        $info = xPathify($html,'/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[4]/tr[2]/td[2]/table/tr');
        $sp = xPathify($html,'/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[4]/tr[2]/td[2]/table/tr[2]/td[2]');
        $temp->sp = $sp->item(0)->nodeValue;

		$next = null;
        for ($i=0;$i<$page->length;$i++) {
            switch ($next) {
                case 1:
                    $temp->goal = $page->item($i)->nodeValue;
                    break;
                case 2:
                    $temp->page = $page->item($i)->nodeValue;
                    break;
                case 3:
                    $temp->when = $page->item($i)->nodeValue;
                    break;
            }
            $next = 0;

            if (strlen(strstr($page->item($i)->nodeValue, 'Målsättning:'))>1) {
                $next = 1;
            }

            if (strlen(strstr($page->item($i)->nodeValue, 'Kursens hemsida:'))>1) {
                $next = 2;
            }

            if (strlen(strstr($page->item($i)->nodeValue, 'Tidpunkt:'))>1) {
                $next = 3;
            }

        }

        for ($i=1;$i<$info->length;$i++){
            $tempArray[$i-1] = $info->item($i)->nodeValue;
        }

        $tempArray2 = preg_split("/[0-9]+/",$tempArray[0]);
        $temp->name = $tempArray2[0];
        return $temp;

    }

    function scrapeSearchedExam($html) {

        // TODO: This should return a list of exam objects to make it easier to handle
        $exams = xPathify($html,'/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/div/table/tr[2]/td[2]/table[1]/tr[1]/td/table/tr');
        print "<br/>Det finns ".($exams->length-1)." tillgänglig(a) för denna kurs<br/>";

		global $currentPage;
        for ($i=1;$i<$exams->length;$i++) {
            $split = explode(')',$exams->item($i)->nodeValue);
            print "Kurs: ".$split[0].") Tent typ:".$split[1]."|  <a href=\"".$currentPage."?action=register&amp;row=".($i-1)."\">Anmäl dig</a> ";
        }

    }

    function scrapeSearchedCourse($html, $pages=null) {
        /*
         * TODO:
         * "Anmäl dig" button
         */


        // Gets the number of spans that are shown in the result
        // html/body/form/table/tbody/tr[2]/td[3]/table/tbody/tr[4]/td/div/div/div/table/tbody/tr[2]/td[2]/table[1]/tbody/tr[2]/td[1]

        $links = xPathify($html, '/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/div/table/tr[2]/td[2]/table[1]/tr[2]/td/span')->length;
        // Nice and short line here, if there are more pages, then this
        // runs xpath, then takes the attribute 'onclick' from the xpathed result
        // explodes it so that we only get the number of pages
        // removes all 's from the string so we get a integer and not a string
        if ($links>0 && $pages==null){
            $pages = str_replace("'", "", explode(',',(xPathify($html, '/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/div/table/tr[2]/td[2]/table[1]/tr[2]/td/span['.$links.']')->item(0)->getAttribute('onclick'))));
            $pages = $pages[1];

        }
        $courses = xPathify($html, '/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/div/table/tr[2]/td[2]/table[1]/tr[1]/td/table/tr');
        for ($i=1; $i<$courses->length ;$i++) {
            print ''.$courses->item($i)->nodeValue.'| <a href=#>Anmäl dig</a><br/>';
        }

		global $currentPage;
        if ($pages>0) {
            print "Number of pages found: ".$pages."<br/>";
            for ($i=1;$i<=$pages;$i++) {
                if ($i != $_GET['p']){
                    if(isset($_POST['course']))
                    print '<a href="'.$currentPage.'?action=searchCourse&amp;course='.$_POST['course'].'&amp;p='.$i.'&amp;maxp='.$pages.'">'.$i.'</a> ';
                    else
                    print '<a href="'.$currentPage.'?action=searchCourse&amp;course='.$_GET['course'].'&amp;p='.$i.'&amp;maxp='.$pages.'">'.$i.'</a> ';

                }
                else print $i." ";
            }
        }
        else print "Only one page found";


    }

    function getExams(){
        $this -> getCourses();
        $results = $this->get($this->mainPage."myRegistrationsMyCourseRegistrations.do?".$this->examPage."&identifier=my_registrations_my_examination_registrations_tab");
        return $results;
    }


    function createEList($html) {
        /*
         * Structure:
         * 0: Titel
         * 1..X: Exams
         */

        
        $list = xPathify($html, "/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[2]/tr/td/table/tr/td/table/tr[1]/td/table/tr");
        ?> 
		<table>
		<thead>
			<tr>
				<th scope="col">Datum</th>
				<th scope="col">Tentamen</th>
				<th scope="col">Förhandsanmälan</th>
				<th scope="col">Status</th>
				<th scope="col">Kursen <br />avklarad</th>
				<th scope="col">Anmälan</th>
				<th scope="col">Stryk</th>
			</tr>
		</thead>
		<tbody>
<?php
        for ($i = 2; $i<=$list->length; $i++) {
            $enroll = "Edrop";
            $exam = xPathify($html, "/html/body/form/table/tr[2]/td[3]/table/tr[4]/td/div/div/table[2]/tr/td/table/tr/td/table/tr[1]/td/table/tr[".$i."]/td");
            $name = explode ("[",$exam->item(1)->nodeValue);
            if (substr(trim($exam->item(5)->nodeValue),1,-1) == "Anmäl") $enroll = "Eenroll";
		    $name[0] = preg_replace('/\h+/', ' ', $name[0]);
		    $name[0] = preg_replace('/\v{3,}/', ' ', $name[0]); 
            echo "<tr><td>".trim($exam->item(0)->nodeValue)."</td><td>".trim($name[0])."</td><td>".trim($exam->item(2)->nodeValue)."</td><td>".trim($exam->item(3)->nodeValue)."</td><td>".trim($exam->item(4)->nodeValue)."</td><td><a href=\"index.php?action=".$enroll."&amp;row=".($i-2)."\"> ".trim($exam->item(5)->nodeValue)."</a></td><td><a href=\"index.php?action=removeExam&amp;row=".($i-2)."\">Stryk</a></td></tr>";
        }
        echo "\n\t\t</tbody></table>";
    }

    function removeExam($row) {
        $this->get($this->mainPage."myRegistrationsMyExaminationRegistrations.do?&actionDispatch=my_registrations_my_examination_registrations_delete&myExaminationRegistrationsListHandler.page[".$row."].callback=true");
    }

    function Eenroll($row) {
        $this->get($this->mainPage."myRegistrationsMyExaminationRegistrations.do?actionDispatch=my_registrations_my_examination_registrations_register&myExaminationRegistrationsListHandler.page[".$row."].callback=true");
        $this->createElist($this->getExams());
    }

    function Edrop($row) {
        $this->get($this->mainPage."myRegistrationsMyExaminationRegistrations.do?actionDispatch=my_registrations_my_examination_registrations_registration_remove&myExaminationRegistrationsListHandler.page[".$row."].callback=true");
        $this->createElist($this->getExams());
    }
	
	function studyPlan() {
		$this->get($this->mainPage."informationMessages.do");
		print utf8_encode($this->get($this->mainPage."myStudyPlanMyStudyPlans.do?actionDispatch=%2Fga_moduletab.do&identifier=my_study_plans"));
	}
}

$scraper = new scraper();
if (isset($_GET['logout'])) {
  $user->logout();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><?php include("head.php");?> 
<body><?php
if (isset($_GET['login']) && $_SERVER["REQUEST_METHOD"] == 'POST') {
  $username = $_POST['username'];
  $password = $_POST['password'];
  $user->login($username, $password);
}
if(!$user->isLoggedIn()){
	include('login.html');
	include('help.html');
} else {
	include('menu.php');?> 
	<div id="wrapper">
		<div id="site"><?php
	if(isset($_GET['action'])) {
		switch($_GET['action']) {
			
		case 'anmal':
			    $content = $page_handler->myCourses();
			    $scraper->createCList($content);
			break;
			
		case 'getCourse':
      if (isset($_GET['course'])) {
        $course = $page_handler->getCourse($_GET['course']);
			        $page = $scraper->scrapeCourse($course);
			        $page->printCourse();
			    }
			    else {
			        echo "No course given";
			    }
			break;
			
		case 'searchExam':
				if (isset($_GET['course'])) {
				    $courseCode = substr($_GET['course'], 0, 8);
				    $scraper->scrapeSearchedExam($scraper->searchExam($courseCode));
				}
			break;
			
		case 'searchCourse':
			    $pageNr=1;
			    if (isset($_GET['p'])) {
			        $pageNr=$_GET['p'];
			    }
			    echo '<form name="mp_course_search" action="?action=searchCourse&p=1" method="POST" enctype="multipart/form-data">';
			    echo 'Kurs: <input type="text" name="course" /> <br/>';
			    echo 'Läsår: <select name="years">';
			    echo '<option value="">Alla</option>';
			    echo '<option value="20082009">2008-2009</option>';
			    echo '<option value="20092010">2009-2010</option>';
			    echo '<option value="20102011">2010-2011</option>';
			    echo '<option value="20112012">2011-2012</option>';
			    echo '<option value="20122013">2012-2013</option>';
			    echo '</select>';
			    echo '<br/><input type="submit" value="Sök">';
			    echo '</form>';
			
			    if (isset($_POST['course'])) {
			    	$years = isset($_POST['years']) ? $_POST['years'] : null;
			        $scraper->scrapeSearchedCourse($scraper->searchCourse($_POST['course'], $_POST['years'], null, $pageNr));
			    }
			    if (isset($_GET['course'])) {
			    	$years = isset($_GET['years']) ? $_GET['years'] : null;
			        $scraper->scrapeSearchedCourse($scraper->searchCourse($_GET['course'], $years, null, $pageNr),$_GET['maxp']);
			    }
			break;
			
		case 'tenter':
      $exam_data = $page_handler->myExaminations();
      $scraper->createElist($exam_data);
			break;
			
		case 'register':
				$scraper->addExam(($_GET['row']));
		        echo "<b>Tentamen har lagts till!</b>";
		        $content = $scraper -> getCourses();
			    $scraper->createCList($content);
			break;
			
		case 'removeExam':
		        $scraper->removeExam($_GET['row']);
		        echo "<b>Tenten har tagits bort!</b>";
			break;
			
		case 'help':
			include('help.html');
			break;

        case 'Edrop':
            $scraper->Edrop($_GET['row']);
            break;
        
       case 'Eenroll':
            $scraper->Eenroll($_GET['row']);
            break;
			
		case 'studyPlan':
				$scraper->studyPlan();
			break;

		case 'search':
		
			/*
			*This will be rewritten when anemos "knows" that his page_handler is working prop.
			*/
		
			// What is beeing searched ? (this should e a function)
			// RegEx for "knowing" if the user is searching with a code or freetext:
			//preg_match("/^(\d{5,6}).(\d)$/", $_POST['searchF'])
			
			// Assumes that the user wants courses that going now
			$cur_year = date(Y)."".(date(Y)+1);
			if ($_POST['courses']=='on' || $_POST['Sall']=='on') {
				$scraper->scrapeSearchedCourse($scraper->searchCourse($_POST['searchF'], $cur_year, null,1));
			}
			if ($_POST['exams']=='on') {
				
			}
			
			break;
		
		default:
			break;
		}
	}?> 
		</div>
	</div><?php
}?> 
</body>
</html>
